import { parseHTML } from "./parse"

// 匹配双大括号
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g

export function compileToFunction(template) {
  let ast = parseHTML(template)
  let renderFnStr = `with(this) { return ${codeGen(ast)} }`
  let render = new Function(renderFnStr)
  return render
}

/**
 * _c("div", null, _c(_s(name) + "hello"))
 */
function codeGen(ast) {
  let code = `_c("${ast.tag}", ${genAttr(ast.attrs)}, ${genChildren(ast.children)})`
  return code
}

function genAttr(attrs) {
  if (!attrs.length) {
    return null
  }
  let attrCode = {}
  attrs.forEach(item => {
    let { name, value } = item
    attrCode[name] = value
    if (name === "style") {
      let stylesObj = {}
      let styles = value.split(";")
      for (const v of styles) {
        let temp = v.split(":")
        let key = temp[0].trim()
        let value = temp[1]
        stylesObj[key] = value
      }
      attrCode[name] = stylesObj
    }
  })
  return JSON.stringify(attrCode)
}

function genChildren(children) {
  if (!children.length) {
    return null
  }
  return children.map(child => genChild(child)).join(", ")
}

function genChild(node) {
  if (node.type === 1) {
    return codeGen(node)
  } else {
    let text = node.text
    if (!defaultTagRE.test(text)) {
      return `_v("${text}")`
    } else {
      let tokens = []
      let match
      let lastIndex = 0
      defaultTagRE.lastIndex = 0
      while ((match = defaultTagRE.exec(text))) {
        let start = match.index
        if (start > lastIndex) {
          tokens.push(JSON.stringify(text.slice(lastIndex, start)))
        }
        tokens.push(`_s(${match[1].trim()})`)
        lastIndex = start + match[0].length
      }
      if (lastIndex < text.length) {
        tokens.push(JSON.stringify(text.slice(lastIndex)))
      }
      return `_v(${tokens.join("+")})`
    }
  }
}
